#include <time.h>
#include <algorithm>
#include "NumberGenerator.h"

NGConfig::NGConfig(Uint32 _possibilities, Uint32 _time, Uint32 _number)
	: Possibilities(_possibilities), Time(_time), Number(_number)
{
}

NGConfig::NGConfig(NGConfig const& _ngConfig)
{
	*this = _ngConfig;
}

NGConfig::~NGConfig()
{
}

NGConfig& NGConfig::operator=(NGConfig const& _ngConfig)
{
	if (this != &_ngConfig)
	{
		Possibilities = _ngConfig.Possibilities;
		Time = _ngConfig.Time;
		Number = _ngConfig.Number;
	}
	return (*this);
}

bool NGConfig::operator==(NGConfig const& _ngConfig) const
{
	return (Possibilities == _ngConfig.Possibilities && Time == _ngConfig.Time && Number == _ngConfig.Number);
}

bool NGConfig::operator!=(NGConfig const& _ngConfig) const
{
	return (!(*this == _ngConfig));
}




NumberGenerator::NumberGenerator(NGConfig const& _config)
	: m_config(_config), m_number(0), m_time(0)
{
	m_values = new Uint32[_config.Possibilities];
	for (int i = 0; i < _config.Possibilities; i++)
		m_values[i] = 0;
}

NumberGenerator::~NumberGenerator()
{
	delete [] m_values;
}

Uint32 NumberGenerator::Generate()
{
	m_number++;
	Uint32 random_integer;
	Uint32 lowest = 0, highest = m_config.Possibilities - 1;
	Uint32 range = (highest-lowest) + 1;
	Uint32 result = lowest + (Uint32)(range * rand() / (RAND_MAX + 1.0));

	m_values[result]++;
	return (result);
}

void NumberGenerator::IncreaseTime()
{
	m_time++;
}

void NumberGenerator::IncreaseNumber()
{
	m_number++;
}

NGConfig& NumberGenerator::GetConfig()
{
	return (m_config);
}

Uint32 NumberGenerator::GetNumber() const
{
	return (m_number);
}

Uint32 NumberGenerator::GetTime() const
{
	return (m_time);
}

static bool mySort(Uint32* _i, Uint32* _j)
{
	return (*_i > *_j);
}

void NumberGenerator::GetResult(std::vector< std::pair<Uint32, Uint32> >& _values, Uint32 _number) const
{
	std::vector<Uint32*> v;
	for (int i = 0; i < m_config.Possibilities; i++)
		v.push_back(&m_values[i]);
	std::sort(v.begin(), v.end(), mySort);
	for (int i = 0; i < v.size() && i < _number; i++)
	{
		int j = 0;
		for (; j < m_config.Possibilities; j++)
			if (v[i] == &m_values[j])
				break ;
		//std::cout << j << ": " << (*v[i]) << std::endl;
		_values.push_back(std::pair<Uint32, Uint32>(j, *v[i]));
	}
}

void NumberGenerator::SetConfig(NGConfig const& _config)
{
	m_config = _config;
}
